﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Licenta1.Expressions;
using Licenta1.Shapes;
using Licenta1.Statements;
using Licenta1.RayTracer;
using Licenta1;
using GoldParser;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace TinyRaytracer
{
    public class MainParsing
    {
        Grammar grammar;
        Statement statement;
        Context context;
        public ArrayList objectsList;
        public bool refresh;
        public Color CurrentColor;
        public RayTracer rt;
        public ArrayList keywords;
        public Bitmap myBitmap;
        public bool btok;
        public int W, H;


        public MainParsing(int width, int height)
        {
            objectsList = new ArrayList();

            string fileName = @"Version12.0.cgt";
            using (Stream stream = File.OpenRead(fileName))
            {
                BinaryReader reader = new BinaryReader(stream);
                grammar = new Grammar(reader);
            }

            myBitmap = new Bitmap(width, height);
            Console.WriteLine("My Bitmap: (" + myBitmap.Width + ", " + myBitmap.Height + ")");
            W = width;
            H = height;
        }



        public bool DoParse(String source)
        {
            //This procedure starts the GOLD Parser Engine and handles each of the
            //messages it returns. Each time a reduction is made, a new instance of a
            //"Simple" object is created and stored in the parse tree. The resulting tree
            //will be a pure representation of the Simple language and will be ready to
            //implement.
            StringReader reader = new StringReader(source);
            Parser parser = new Parser(reader, grammar);
            parser.TrimReductions = true;
            context = new Context(parser, this);
            //            //Console.WriteLine("Context: " + context.ToString());
            //            //onOut.Log("Ctext.var " + context.variables.ToString());
            while (true)
            {
                switch (parser.Parse())
                {
                    case ParseMessage.LexicalError:
                        Console.WriteLine("LEXICAL ERROR. Line " + parser.LineNumber + ". Cannot recognize token: " + parser.TokenText);
                        return false;

                    case ParseMessage.SyntaxError:
                        StringBuilder text = new StringBuilder();
                        foreach (Symbol tokenSymbol in parser.GetExpectedTokens())
                        {
                            text.Append(' ');
                            text.Append(tokenSymbol.ToString());
                        }
                        Console.WriteLine("SYNTAX ERROR. Line " + parser.LineNumber + ". Expecting:" + text.ToString());
                        return false;

                    case ParseMessage.Reduction:
                        //== Create a new customized object and replace the
                        //== CurrentReduction with it. This saves memory and allows
                        //== easier interpretation
                        Node n = context.GetObject();
                        //                        Log("Reduction: Type added in the parser tree: " + n.ToString());
                        parser.TokenSyntaxNode = context.GetObject();
                        break;

                    case ParseMessage.Accept:
                        //=== Success!
                        statement = (Statement)parser.TokenSyntaxNode;
                        Console.WriteLine("-- Program Accepted --");
                        return true;

                    case ParseMessage.TokenRead:
                        //=== Make sure that we store token string for needed tokens.
                        parser.TokenSyntaxNode = context.GetTokenText();
                        break;

                    case ParseMessage.InternalError:
                        Console.WriteLine("INTERNAL ERROR! Something is horribly wrong");
                        return false;

                    case ParseMessage.NotLoadedError:
                        //=== Due to the if-statement above, this case statement should never be true
                        Console.WriteLine("NOT LOADED ERROR! Compiled Grammar Table not loaded");
                        return false;

                    case ParseMessage.CommentError:
                        Console.WriteLine("COMMENT ERROR! Unexpected end of file");
                        return false;

                    case ParseMessage.CommentBlockRead:
                        //=== Do nothing
                        break;

                    case ParseMessage.CommentLineRead:
                        //=== Do nothing
                        break;
                }
            }
        }


        public void execute(int x, int y, int width, int height)
        {
            if (statement != null)
            {
                context.variables.Clear();
                statement.Execute();
            }

            if (rt != null)
            {
                Bitsmap b = new Bitsmap(context, rt.GetPixel, x, y, width, height);
            }
        }

        public void save(String name, int start_x, int start_y, int end_x, int end_y)
        {
            MemoryStream ms = new MemoryStream();
            Bitmap newBitmap = new Bitmap(end_x - start_x, end_y - start_y);

            for (int i = 0; i < newBitmap.Width; i++)
                for (int j = 0; j < newBitmap.Height; j++)
                    newBitmap.SetPixel(i, j, myBitmap.GetPixel(i + start_x, j + start_y));

            newBitmap.Save(ms, ImageFormat.Png);

            FileStream fs = new FileStream(name + ".png", FileMode.Create);
            ms.WriteTo(fs);
            ms.Close();
            fs.Close();
            myBitmap.Dispose();
        }

        public class ObjectToDraw
        {
            string name;
            public Shape s;
            Color color;
            public Pen pen;

            public ObjectToDraw(string name, Shape s, Color c, Pen p)
            {
                this.name = name;
                this.s = s;
                color = c;
                pen = p;
            }

        }
    }
}
